package com.iflytek.autoCompareTool.model;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.iflytek.autoCompareTool.utils.XLSXWrite;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author llchen12
 * @date 2018/6/5
 */
public class OutputData {

    private final static int APPID = 0;
    private final static int USERID = 1;
    private final static int PARAMETER = 2;
    private final static int UID = 3;
    private final static int USER_DATA = 4;
    private final static int TEXT = 5;
    private final static int BASE_SERVICE = 6;
    private final static int BASE_SEMANTIC = 7;
    private final static int BASE_OPEARTION = 8;
    private final static int BASE_ANSWER = 9;
    private final static int CMP_SERVICE = 10;
    private final static int CMP_SEMANTIC = 11;
    private final static int CMP_OPEARTION = 12;
    private final static int CMP_ANSWER = 13;
    private final static int RESULT_SERVICE = 14;
    private final static int RESULT_SEMANTIC = 15;
    private final static int RESULT_OPEARTION = 16;
    private final static int RESULT_ANSWER = 17;
    private final static int BASE_UUID = 18;
    private final static int CMP_UUID = 19;
    private final static int BASE_URL = 20;
    private final static int CMP_URL = 21;

    private String fileName;

    private XLSXWrite rightXlsxWrite;

    private List<XLSXWrite> diffXlsxWrites;

    private InputInfo inputInfo;

    private Map<Integer, OutputInfo> dataMap;

    private Map<String, List<OutputInfo>> diffMap;

    private AtomicInteger count = new AtomicInteger(1);

    public OutputData(String fileName, InputInfo inputInfo) {
        this.fileName = fileName;
        this.inputInfo = inputInfo;
        this.dataMap = new HashMap<>();
        this.diffMap = new LinkedHashMap<>();
        this.rightXlsxWrite = new XLSXWrite();
        this.diffXlsxWrites = new ArrayList<>();
        createSheetTitle();
    }


    private void createSheetTitle() {
        String baseName = getEnvToName(inputInfo.getBaseEnv());
        String cmpName = getEnvToName(inputInfo.getCmpEnv());

        rightXlsxWrite.setCellValue(0, APPID, "appid", false);
        rightXlsxWrite.setCellValue(0, USERID, "usrid", false);
        rightXlsxWrite.setCellValue(0, PARAMETER, "自定义参数", false);
        rightXlsxWrite.setCellValue(0, UID, "uid", false);
        rightXlsxWrite.setCellValue(0, USER_DATA, "user_data", false);
        rightXlsxWrite.setCellValue(0, TEXT, "text", false);
        if (inputInfo.getSingleEnv() != 1) {
            rightXlsxWrite.setCellValue(0, BASE_SERVICE, "service" + baseName, false);
            rightXlsxWrite.setCellValue(0, BASE_SEMANTIC, "semantic" + baseName, false);
            rightXlsxWrite.setCellValue(0, BASE_OPEARTION, "operation" + baseName, false);
            rightXlsxWrite.setCellValue(0, BASE_ANSWER, "answer" + baseName, false);
            rightXlsxWrite.setCellValue(0, CMP_SERVICE, "service" + cmpName, false);
            rightXlsxWrite.setCellValue(0, CMP_SEMANTIC, "semantic" + cmpName, false);
            rightXlsxWrite.setCellValue(0, CMP_OPEARTION, "operation" + cmpName, false);
            rightXlsxWrite.setCellValue(0, CMP_ANSWER, "answer" + cmpName, false);
        } else {
            rightXlsxWrite.setCellValue(0, 6, "service" + cmpName, false);
            rightXlsxWrite.setCellValue(0, 7, "semantic" + cmpName, false);
            rightXlsxWrite.setCellValue(0, 8, "operation" + cmpName, false);
            rightXlsxWrite.setCellValue(0, 9, "answer" + cmpName, false);
        }
        if (inputInfo.getSingleEnv() != 1) {
            rightXlsxWrite.setCellValue(0, RESULT_SERVICE, "service对比", false);
            rightXlsxWrite.setCellValue(0, RESULT_SEMANTIC, "semantic对比", false);
            rightXlsxWrite.setCellValue(0, RESULT_OPEARTION, "operation对比", false);
            rightXlsxWrite.setCellValue(0, RESULT_ANSWER, "answer对比", false);
            rightXlsxWrite.setCellValue(0, BASE_UUID, "uuid" + baseName, false);
            rightXlsxWrite.setCellValue(0, CMP_UUID, "uuid" + cmpName, false);
            rightXlsxWrite.setCellValue(0, BASE_URL, baseName + "URL", false);
            rightXlsxWrite.setCellValue(0, CMP_URL, cmpName + "URL", false);

            rightXlsxWrite.setCellValue(0, 22, baseName + "sid", false);
            rightXlsxWrite.setCellValue(0, 23, cmpName + "sid", false);
        } else {
            rightXlsxWrite.setCellValue(0, 10, "uuid" + cmpName, false);
            rightXlsxWrite.setCellValue(0, 11, "状态", false);
            rightXlsxWrite.setCellValue(0, 12, cmpName + "URL", false);
            rightXlsxWrite.setCellValue(0, 13, cmpName + "sid", false);
        }
    }

    private String getEnvToName(String env) {
        if ("expect".equals(env)) {
            return "标注";
        } else if ("online".equals(env)) {
            return "雅典娜";
        } else if ("onlinepre".equals(env)) {
            return "准上线";
        } else if ("nlu_test".equals(env)) {
            return "语义测试";
        } else if ("athena_move".equals(env)) {
            return "雅典娜迁移测试";
        } else if ("kcloud_current".equals(env)) {
            return "知识云现网";
        } else if ("kcloud_move_pk".equals(env)) {
            return "知识云迁移PK";
        } else if ("kcloud_move_nlu".equals(env)) {
            return "知识云迁移NLU";
        }
        return "";
    }

    /**
     * 产生对比结果
     */
    public synchronized void add(OutputInfo outputInfo) throws Exception {
        int index = outputInfo.getNum();
        int curIndex = count.get();
        if (curIndex == index) {
            count.getAndIncrement();
            addToExcel(outputInfo, curIndex);
            while (dataMap.containsKey(++curIndex)) {
                addToExcel(dataMap.get(curIndex), curIndex);
                dataMap.remove(curIndex);
                count.getAndIncrement();
            }
        } else {
            dataMap.put(index, outputInfo);
        }
    }


    /**
     * 保存待处理的不一致对比结果
     */
    public synchronized void addDiff(OutputInfo outputInfo) throws Exception {
        int index = outputInfo.getNum();
        int curIndex = count.get();
        if (curIndex == index) {
            count.getAndIncrement();
            putDiffMap(outputInfo);
            while (dataMap.containsKey(++curIndex)) {
                putDiffMap(dataMap.get(curIndex));
                dataMap.remove(curIndex);
                count.getAndIncrement();
            }
        } else {
            dataMap.put(index, outputInfo);
        }
    }

    /**按uid+filename分组**/
    private void putDiffMap(OutputInfo outputInfo){
        String uid = outputInfo.getUid()+outputInfo.getFileName();
        if (diffMap.containsKey(uid)){
            diffMap.get(uid).add(outputInfo);
        }else {
            List<OutputInfo> list = new ArrayList<>();
            list.add(outputInfo);
            diffMap.put(uid,list);
        }
    }


    private void addToExcel(OutputInfo outputData, int index) throws Exception {
        rightXlsxWrite.setCellValue(index, APPID, outputData.getAppid(), false);
        rightXlsxWrite.setCellValue(index, USERID, outputData.getUsrid(), false);
        rightXlsxWrite.setCellValue(index, PARAMETER, outputData.getParameter(), false);
        rightXlsxWrite.setCellValue(index, UID, outputData.getUid(), false);
        rightXlsxWrite.setCellValue(index, USER_DATA, outputData.getUserData(), false);
        rightXlsxWrite.setCellValue(index, TEXT, outputData.getText(), false);
        if (inputInfo.getSingleEnv() != 1) {
            rightXlsxWrite.setCellValue(index, BASE_SERVICE, outputData.getBaseService(), false);
            rightXlsxWrite.setCellValue(index, BASE_SEMANTIC, getJson(outputData.getBaseSemantic()), false);
            rightXlsxWrite.setCellValue(index, BASE_OPEARTION, outputData.getBaseOperation(), false);
            rightXlsxWrite.setCellValue(index, BASE_ANSWER, outputData.getBaseAnswer(), false);
            rightXlsxWrite.setCellValue(index, CMP_SERVICE, outputData.getClService(), false);
            rightXlsxWrite.setCellValue(index, CMP_SEMANTIC, getJson(outputData.getClSemantic()), false);
            rightXlsxWrite.setCellValue(index, CMP_OPEARTION, outputData.getClOperation(), false);
            rightXlsxWrite.setCellValue(index, CMP_ANSWER, outputData.getClAnswer(), false);
        } else {
            rightXlsxWrite.setCellValue(index, 6, outputData.getClService(), false);
            rightXlsxWrite.setCellValue(index, 7, getJson(outputData.getClSemantic()), false);
            rightXlsxWrite.setCellValue(index, 8, outputData.getClOperation(), false);
            rightXlsxWrite.setCellValue(index, 9, outputData.getClAnswer(), false);
        }
        if (inputInfo.getSingleEnv() != 1) {
            rightXlsxWrite.setCellValue(index, RESULT_SERVICE, outputData.getCmpService(), false);
            rightXlsxWrite.setCellValue(index, RESULT_SEMANTIC, outputData.getCmpSemantic(), false);
            rightXlsxWrite.setCellValue(index, RESULT_OPEARTION, outputData.getCmpOperation(), false);
            rightXlsxWrite.setCellValue(index, RESULT_ANSWER, outputData.getCmpAnswer(), false);
            rightXlsxWrite.setCellValue(index, BASE_UUID, outputData.getBaseUuid(), false);
            rightXlsxWrite.setCellValue(index, CMP_UUID, outputData.getC1Uuid(), false);
            rightXlsxWrite.setCellValue(index, BASE_URL, outputData.getBaseUrl(), false);
            rightXlsxWrite.setCellValue(index, CMP_URL, outputData.getC1Url(), false);
            rightXlsxWrite.setCellValue(index, 22, outputData.getBaseSid(), false);
            rightXlsxWrite.setCellValue(index, 23, outputData.getC1Sid(), false);
        } else {
            rightXlsxWrite.setCellValue(index, 10, outputData.getC1Uuid(), false);
            rightXlsxWrite.setCellValue(index, 11, outputData.getCmpSemantic(), true);
            rightXlsxWrite.setCellValue(index, 12, outputData.getC1Url(), false);
            rightXlsxWrite.setCellValue(index, 13, outputData.getC1Sid(), false);
        }

    }

    /**取出有diff结果的会话集，进行输出**/
    public void saveDiff() throws Exception {
        List<OutputInfo> output;
        //标记有diff的会话
        Set<String> diffUids = new LinkedHashSet<>();
        //查看哪些会话的结果集中有diff
        for (String key:diffMap.keySet()){
            output = diffMap.get(key);
            for (OutputInfo outputDataInfo:output){
                if (outputDataInfo.getFinalResult()!=null){
                    diffUids.add(outputDataInfo.getUid()+outputDataInfo.getFileName());
                }
            }
        }
        //将含有diff的会话集取出，进行add到输出excel流
        int rowIndex = 1;
        int sheetIndex = 0;
        for (String diffUID:diffUids){
            List<OutputInfo> aiuiOutputDataInfos = diffMap.get(diffUID);
            for (OutputInfo aiuiOutputDataInfo:aiuiOutputDataInfos){
                if (rowIndex==1){
                    rightXlsxWrite.newSheetXLSXWrite(sheetIndex,"不一致部分");
                    createSheetTitle2();
                }
                addDiffToExcel(aiuiOutputDataInfo,rowIndex++,aiuiOutputDataInfo.getFileName());
            }
        }

        //若没有不一致结果，进行说明
        if (diffUids.isEmpty()){
            rightXlsxWrite.setCellValue(1, APPID, "该任务没有不一致结果。请查看其他结果集文件进行确认。", false);
        }else {
            //删除第一个空的sheet
            rightXlsxWrite.removeSheetOne();
        }
        rightXlsxWrite.writeToFile(this.fileName);
    }

    private void createSheetTitle2(){
        String baseName = getEnvToName(inputInfo.getBaseEnv());
        String cmpName = getEnvToName(inputInfo.getCmpEnv());

        rightXlsxWrite.setCellValue(0, 0, "filename", false);
        rightXlsxWrite.setCellValue(0, APPID+1, "appid", false);
        rightXlsxWrite.setCellValue(0, USERID+1, "usrid", false);
        rightXlsxWrite.setCellValue(0, PARAMETER+1, "自定义参数", false);
        rightXlsxWrite.setCellValue(0, UID+1, "uid", false);
        rightXlsxWrite.setCellValue(0, USER_DATA+1, "user_data", false);
        rightXlsxWrite.setCellValue(0, TEXT+1, "text", false);
        if (inputInfo.getSingleEnv()!=1){
            rightXlsxWrite.setCellValue(0, BASE_SERVICE+1, "service"+baseName, false);
            rightXlsxWrite.setCellValue(0, BASE_SEMANTIC+1, "semantic"+baseName, false);
            rightXlsxWrite.setCellValue(0, BASE_OPEARTION+1, "operation"+baseName, false);
            rightXlsxWrite.setCellValue(0, BASE_ANSWER+1, "answer"+baseName, false);
            rightXlsxWrite.setCellValue(0, CMP_SERVICE+1, "service"+cmpName, false);
            rightXlsxWrite.setCellValue(0, CMP_SEMANTIC+1, "semantic"+cmpName, false);
            rightXlsxWrite.setCellValue(0, CMP_OPEARTION+1, "operation"+cmpName , false);
            rightXlsxWrite.setCellValue(0, CMP_ANSWER+1, "answer"+cmpName , false);
        }else {
            rightXlsxWrite.setCellValue(0, 6+1, "service"+cmpName, false);
            rightXlsxWrite.setCellValue(0, 7+1, "semantic"+cmpName, false);
            rightXlsxWrite.setCellValue(0, 8+1, "operation"+cmpName , false);
            rightXlsxWrite.setCellValue(0, 9+1, "answer"+cmpName , false);
        }
        if (inputInfo.getSingleEnv()!=1){
            rightXlsxWrite.setCellValue(0, RESULT_SERVICE+1, "service对比" , false);
            rightXlsxWrite.setCellValue(0, RESULT_SEMANTIC+1, "semantic对比" , false);
            rightXlsxWrite.setCellValue(0, RESULT_OPEARTION+1, "operation对比", false);
            rightXlsxWrite.setCellValue(0, RESULT_ANSWER+1, "answer对比", false);
            rightXlsxWrite.setCellValue(0, BASE_UUID+1, "uuid"+baseName, false);
            rightXlsxWrite.setCellValue(0, CMP_UUID+1, "uuid"+cmpName, false);
            rightXlsxWrite.setCellValue(0, BASE_URL+1, baseName+"URL", false);
            rightXlsxWrite.setCellValue(0, CMP_URL+1, cmpName+"URL", false);

            rightXlsxWrite.setCellValue(0, 22+1, baseName+"sid", false);
            rightXlsxWrite.setCellValue(0, 23+1, cmpName+"sid", false);
        }else {
            rightXlsxWrite.setCellValue(0, 10+1, "uuid"+cmpName, false);
            rightXlsxWrite.setCellValue(0, 11+1, "状态" , false);
            rightXlsxWrite.setCellValue(0, 12+1, cmpName+"URL", false);
            rightXlsxWrite.setCellValue(0, 13+1, cmpName+"sid", false);
        }
    }

    private void addDiffToExcel(OutputInfo outputData, int index,String fileName){
        rightXlsxWrite.setCellValue(index, 0, fileName, false);
        rightXlsxWrite.setCellValue(index, APPID+1, outputData.getAppid(), false);
        rightXlsxWrite.setCellValue(index, USERID+1, outputData.getUsrid(), false);
        rightXlsxWrite.setCellValue(index, PARAMETER+1, outputData.getParameter(), false);
        rightXlsxWrite.setCellValue(index, UID+1, outputData.getUid(), false);
        rightXlsxWrite.setCellValue(index, USER_DATA+1, outputData.getUserData(), false);
        rightXlsxWrite.setCellValue(index, TEXT+1, outputData.getText(), false);
        if (inputInfo.getSingleEnv()!=1) {
            rightXlsxWrite.setCellValue(index, BASE_SERVICE+1, outputData.getBaseService(), false);
            rightXlsxWrite.setCellValue(index, BASE_SEMANTIC+1, getJson(outputData.getBaseSemantic()), false);
            rightXlsxWrite.setCellValue(index, BASE_OPEARTION+1, outputData.getBaseOperation(), false);
            rightXlsxWrite.setCellValue(index, BASE_ANSWER+1, outputData.getBaseAnswer(), false);
            rightXlsxWrite.setCellValue(index, CMP_SERVICE+1, outputData.getClService(), false);
            rightXlsxWrite.setCellValue(index, CMP_SEMANTIC+1, getJson(outputData.getClSemantic()), false);
            rightXlsxWrite.setCellValue(index, CMP_OPEARTION+1, outputData.getClOperation() , false);
            rightXlsxWrite.setCellValue(index, CMP_ANSWER+1, outputData.getClAnswer() , false);
        }else {
            rightXlsxWrite.setCellValue(index, 6+1, outputData.getClService(), false);
            rightXlsxWrite.setCellValue(index, 7+1,getJson(outputData.getClSemantic()), false);
            rightXlsxWrite.setCellValue(index, 8+1, outputData.getClOperation() , false);
            rightXlsxWrite.setCellValue(index, 9+1, outputData.getClAnswer() , false);
        }
        if (inputInfo.getSingleEnv()!=1){
            rightXlsxWrite.setCellValue(index, RESULT_SERVICE+1, outputData.getCmpService() , false);
            rightXlsxWrite.setCellValue(index, RESULT_SEMANTIC+1, outputData.getCmpSemantic() , false);
            rightXlsxWrite.setCellValue(index, RESULT_OPEARTION+1, outputData.getCmpOperation(), false);
            rightXlsxWrite.setCellValue(index, RESULT_ANSWER+1, outputData.getCmpAnswer(), false);
            rightXlsxWrite.setCellValue(index, BASE_UUID+1, outputData.getBaseUuid(), false);
            rightXlsxWrite.setCellValue(index, CMP_UUID+1, outputData.getC1Uuid(), false);
            rightXlsxWrite.setCellValue(index, BASE_URL+1, outputData.getBaseUrl(), false);
            rightXlsxWrite.setCellValue(index, CMP_URL+1, outputData.getC1Url(), false);
            rightXlsxWrite.setCellValue(index, 22+1, outputData.getBaseSid(), false);
            rightXlsxWrite.setCellValue(index, 23+1, outputData.getC1Sid(), false);
        }else {
            rightXlsxWrite.setCellValue(index, 10+1, outputData.getC1Uuid(), false);
            rightXlsxWrite.setCellValue(index, 11+1, outputData.getCmpSemantic() , true);
            rightXlsxWrite.setCellValue(index, 12+1, outputData.getC1Url(), false);
            rightXlsxWrite.setCellValue(index, 13+1, outputData.getC1Sid(), false);
        }
    }


    private String getJson(JSONObject jsonObject) {
        return jsonObject == null ? "" : JSON.toJSONString(jsonObject, true);
    }

    public void save() {
        rightXlsxWrite.writeToFile(fileName);
    }

    public void close(){
        rightXlsxWrite.close();
    }

}
